package com.ruoyi.lvlian.controller;

import java.util.*;

import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.lvlian.domain.*;
import com.ruoyi.lvlian.dto.InvoiceInfoDto;
import com.ruoyi.lvlian.service.ICommonService;
import com.ruoyi.lvlian.service.InvoiceInfoService;
import com.ruoyi.lvlian.vo.*;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

/**
 * 发票信息Controller
 *
 * @author liyuxi
 * @date 2024-05-09
 */
@Api(value = "税务发票管理", tags = "税务发票管理接口")
@ApiResponses(@ApiResponse(code = 200, message = "接口请求成功"))
@RestController
@RequestMapping("/invoiceInfo")
public class InvoiceInfoController extends BaseController {
    @Autowired
    private InvoiceInfoService invoiceInfoService;
    @Autowired
    private ICommonService iCommonService;

    /**
     * 查询发票信息列表
     */
//    //@RequiresPermissions("lvlian:invoiceInfo:list")
    @GetMapping("/list")
    @ApiOperation("基本废弃查询税务发票信息列表")
    public R<TableDataInfo> list(InvoiceInfoDto invoiceInfo) {
        startPage();

        if (StringUtils.isEmpty(invoiceInfo.getTaxRate())) {

            return R.fail(400, "税率不能为空");
        }
/*     invoiceInfo.setOrgCodes(invoiceInfo.getOrgCode().split(","));

        if (invoiceInfo.getOrgCode().contains("50000000")) {
            invoiceInfo.setOrgCode("50000000");
            invoiceInfo.setOrgCodes("50000000".split(","));
        }*/
        List<InvoiceVo> list = invoiceInfoService.selectInvoiceInfoList(invoiceInfo);
        return R.ok(getDataTable(list));

    }

    private String validateInData(InvoiceInfoDto invoiceInfo) {
        if (StringUtils.isEmpty(invoiceInfo.getContractNum())) {
            return "合同编号不能为空";
        }
        return "success";
    }

//一张入库单 可能会有2 ，3张发票

    @GetMapping("/queryInvoiceInfoList")
    @ApiOperation("2.0 专用使用查询税务发票信息列表")
    public R<TableDataInfo> queryInvoiceInfoList(InvoiceInfoDto invoiceInfo) {
        if (SecurityUtils.getUserId() == 1) {
            invoiceInfo.setOrgCodes(new ArrayList<>(Arrays.asList("50000000")));
        } else {
            List<String> orgCodes = iCommonService.queryCurrentOrgCode(SecurityUtils.getUserId());
            if (orgCodes.size() == 0) {
                return R.fail("暂未分配账本");
            }
            if (Objects.isNull(invoiceInfo.getOrgCodes()) || invoiceInfo.getOrgCodes().isEmpty()) {
                orgCodes.removeIf(code -> code.length() != 8);
                invoiceInfo.setOrgCodes(orgCodes);
            }
        }
        if (StringUtils.isNotEmpty(invoiceInfo.getInNum()) || StringUtils.isNotEmpty(invoiceInfo.getOutNum())) {
            if (StringUtils.isEmpty(invoiceInfo.getBuyerName())) {
                return R.fail("入库单和购买方名称,销售方名称 需要同时有值");
            }
            if (invoiceInfo.getSettlementAmount() < 1) {
                return R.fail("结算金额不能为空");
            }
        }
        startPage();
        List<InvoiceVo> list = invoiceInfoService.queryInvoiceInfoList(invoiceInfo);
        return R.ok(getDataTable(list));

    }


    @GetMapping("/queryInvoiceInfoAgg")
    @ApiOperation("税务看板")
    public AjaxResult queryInvoiceInfoAgg(@ApiParam(value = "采购/销售", required = true) @RequestParam(value = "category") String category, @ApiParam(value = "入库单号/销售方出库单号", required = true) @RequestParam(value = "warehouseNum") String warehouseNum, @ApiParam(value = "结算金额", required = true) @RequestParam(value = "settlementAmount") String settlementAmount, @ApiParam(value = "购买方名称", required = true) @RequestParam(value = "buyerName") String buyerName, @ApiParam(value = "销售方名称", required = true) @RequestParam(value = "sellerName") String sellerName) {

        return success(invoiceInfoService.queryInvoiceInfoAgg(category, warehouseNum, settlementAmount, buyerName, sellerName));
    }

    @ApiOperation("查询税务发票信息单个 getInfoById")
    @GetMapping("/getInfoById")
    public AjaxResult getInfoById(@ApiParam(value = "发票ID Fp", required = true) @RequestParam(value = "id") String id) {
        InvoiceVo invoiceInfo = invoiceInfoService.selectInvoiceInfoById(id);
        return success(invoiceInfo);
    }

    /**
     * 查询发票信息详情-支付回单显示
     */
    //@RequiresPermissions("lvlian:invoiceInfo:query")
    @GetMapping("/getDetails")
    // @Cacheable(value = "scfInvoiceDetailsCache", key = "'scfInvoiceDetailsCacheKey-' + #scfInvoiceInfo.rowId")
    public R<TableDataInfo> detail(InvoiceInfoDto invoiceInfo) {// 实际传参只有发票的Id
        startPage();
        return R.ok(getDataTable(invoiceInfoService.details(invoiceInfo)));
    }


    /**
     * 新增发票信息
     * http://localhost:8080/lvlian/invoiceInfo/list?invoiceType=caigou&pageNum=1&pageSize=10
     */
/*    //@RequiresPermissions("lvlian:invoiceInfo:add")
    @Log(title = "发票信息", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    public AjaxResult add(@RequestBody InvoiceInfo invoiceInfo) throws Exception {

        if (!"success".equalsIgnoreCase(validateInData(invoiceInfo))) {
            return error(validateInData(invoiceInfo));
        }

        AjaxResult ajax = toAjax(invoiceInfoService.insertInvoiceInfo(invoiceInfo));
        return ajax;
    }*/
    private String validateInData(InvoiceInfo po) {
        if (StringUtils.isEmpty(po.getInvoiceNum())) {
            return "发票号码不能为空";
        }
        return "success";
    }


    /**
     * 修改发票信息
     */
    //@RequiresPermissions("lvlian:invoiceInfo:edit")
    @Log(title = "发票信息", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody @Validated InvoiceInfo invoiceInfo) {

        if (!"success".equalsIgnoreCase(validateInData(invoiceInfo))) {
            return error(validateInData(invoiceInfo));
        }

        return toAjax(invoiceInfoService.updateInvoiceInfo(invoiceInfo));
    }


    @ApiOperation("修改发票信息详情")
    @PostMapping("/modifyInvoiceDetails")
    // @CacheEvict(value = "scfInvoiceDetailsCache", key = "'scfInvoiceDetailsCacheKey-' + #scfInvoiceInfo.rowId")
    public AjaxResult update(@RequestBody InvoiceInfo invoiceInfo) {
        return toAjax(invoiceInfoService.updateInvoiceInfo(invoiceInfo));
    }


    @ApiOperation("查询发票关联支付列表(修改关联使用)")
    @ApiImplicitParams({@ApiImplicitParam(name = "invoiceId", value = "发票Id")})
    @GetMapping("/queryInvoicePaymentInfoRefList")
    public LvlianTableDataInfoVo queryInvoicePaymentInfoRefList(@RequestParam(value = "invoiceId", required = true) String invoiceId) {
        LvlianTableDataInfoVo tableDataInfoVo = new LvlianTableDataInfoVo();
        startPage();
        List<PaymentInfoVo> list = invoiceInfoService.queryInvoicePaymentInfoRefList(invoiceId);
        // 计算总的剩余金额
        double sum = list.stream().mapToDouble(PaymentInfoVo::getShengyuAmount).sum();
        tableDataInfoVo.setCode(HttpStatus.SUCCESS);
        tableDataInfoVo.setRows(list);
        // 设置总的剩余金额
        tableDataInfoVo.setTotalShengyuAmount(sum);
        tableDataInfoVo.setMsg("查询成功");
        tableDataInfoVo.setTotal(new PageInfo(list).getTotal());
        return tableDataInfoVo;
    }

/*
    @ApiOperation("查询发票关联的再生入库列表(修改关联使用)")
    @ApiImplicitParams({@ApiImplicitParam(name = "invoiceId", value = "发票Id")})
    @GetMapping("/queryInvoiceRenewableInInfoRefList")
    public TableDataInfo queryInvoiceRenewableInInfoRefList(@RequestParam(value = "invoiceId", required = true) String invoiceId) {
        startPage();
        List<RenewableInInfoVo> list = invoiceInfoService.queryInvoiceRenewableInInfoRefList(invoiceId);
        return getDataTable(list);
    }
*/



/*
    @ApiOperation("发票保存支付")
    @PostMapping("/addInvoicePaymentUseAmountList")
    public AjaxResult addInvoicePaymentUseAmountList(@RequestBody InvoicePaymentDetailDto invoicePaymentDetailDto) {
        return toAjax(invoiceInfoService.addInvoicePaymentUseAmountList(invoicePaymentDetailDto));
    }
*/

    @ApiOperation("删除发票关联支付")
    @PostMapping("/deleteInvoicePaymentUseAmountList")
    public AjaxResult deleteInvoicePaymentUseAmountList(@RequestParam("invoiceId") String invoiceId, @RequestParam("paymentId") String paymentId) {
        return toAjax(invoiceInfoService.deleteInvoicePaymentUseAmountList(invoiceId, paymentId));
    }

    @PostMapping("/remove")
    @Log(title = "删除发票", businessType = BusinessType.DELETE)
    public AjaxResult remove(@RequestBody String[] ids) {
        if( ids == null || ids.length == 0  ){
            return error("未选中") ;
        }
        return toAjax(invoiceInfoService.deleteInvoiceInfoByIds(ids));
    }


/*
    @GetMapping("/queryRenewableInInfoJoinContractList")
    @ApiOperation("再生关联合同信息 ，点击购买方入库单 (内页使用)")
    public TableDataInfo queryRenewableInInfoJoinContractList(RenewableInInfoDto renewableInInfoDto) {
        if (org.apache.commons.lang3.StringUtils.isEmpty(renewableInInfoDto.getSellerName())) {
            renewableInInfoDto.setSellerName(renewableInInfoDto.getInvoicerName());
        }
        startPage();
        List<RenewableInInfoVo> list = invoiceInfoService.queryRenewableInInfoJoinContractList(renewableInInfoDto);
        return getDataTable(list);
    }
*/


    @ApiOperation("根据发票号码查物流结算金额")
    @GetMapping("/querySettlementAmountByInvoiceNum")
    public AjaxResult querySettlementAmountByInvoiceNum(@Validated @RequestParam(value = "invoiceNum", required = true) @NotBlank(message = "发票号码不能为空") String invoiceNum) {
        if (StringUtils.isEmpty(invoiceNum)) {
            AjaxResult.error("发票号码不能为空");
        }
        List<HashMap<String, Object>> wuliu = invoiceInfoService.querySettlementAmountByInvoiceNum(invoiceNum);

        return AjaxResult.success(wuliu);
    }


    @ApiOperation("根据发票号码查支付交易金额")
    @GetMapping("/queryPaymentAmountByInvoiceNum")
    public AjaxResult queryPaymentAmountByInvoiceNum(@Validated @RequestParam(value = "invoiceNum", required = true) @NotBlank(message = "发票号码不能为空") String invoiceNum) {
        if (StringUtils.isEmpty(invoiceNum)) {
            AjaxResult.error("发票号码不能为空");
        }
        List<HashMap<String, Object>> payment = invoiceInfoService.queryPaymentAmountByInvoiceNum(invoiceNum);
        return AjaxResult.success(payment);
    }

    @ApiOperation("根据发票号码查合同信息")
    @GetMapping("/queryContractInfoByInvoiceNum")
    public AjaxResult queryContractInfoByInvoiceNum(@Validated @RequestParam(value = "invoiceNum", required = true) @NotBlank(message = "发票号码不能为空") String invoiceNum) {
        if (StringUtils.isEmpty(invoiceNum)) {
            AjaxResult.error("发票号码不能为空");
        }
        List<HashMap<String, Object>> wuliu = invoiceInfoService.queryContractInfoByInvoiceNum(invoiceNum);
        return AjaxResult.success(wuliu);
    }


    @ApiOperation("导入发票百分之十三")
    @PostMapping("/importInfoThirteenPercent")
    public AjaxResult importInfoThirteenPercent(MultipartFile file) {
        // 获取到批量导入的数据集合
        List<InvoiceInfo> dtoList = null;
        List<InvoiceInfo> newList = new ArrayList<>();

        try {
            dtoList = invoiceInfoService.importInfo(file, "13%发票信息", 3);
            for (InvoiceInfo po : dtoList) {
                if (StringUtils.isEmpty(po.getOrgCode()) || StringUtils.isEmpty(po.getBuyerName()) || StringUtils.isEmpty(po.getSellerName())) {
                    continue;
                }

                newList.add(po);
            }
            invoiceInfoService.bachSave(newList);


        } catch (Exception e) {
            e.printStackTrace();
            return success("模板错误");
        }

        String msg = "解析到" + dtoList.size() + "条数据，" + "导入成功" + newList.size() + "条，导入失败" + (dtoList.size() - newList.size()) + "条！";
        return success(msg);
    }


    @ApiOperation("导入发票批次")
    @PostMapping("/importInfoDetails")
    public AjaxResult importInfoDetails(MultipartFile file, int percent) {
        // 获取到批量导入的数据集合
        List<InvoiceDetails> dtoList = null;
        List<InvoiceDetails> newList = new ArrayList<>();
        int totalSussess = 0;
        try {
            if (13 == percent) {
                dtoList = invoiceInfoService.importInvoiceDetails(file, "13%发票批次", 3);

            } else if (3 == percent) {
                dtoList = invoiceInfoService.importInvoiceDetails(file, "3%发票批次", 3);
            } else if (1 == percent) {
                dtoList = invoiceInfoService.importInvoiceDetails(file, "1%发票批次", 3);
            } else {
                return success("参数比例错误 1 3 13");
            }

            for (InvoiceDetails po : dtoList) {
                newList.add(po);
            }

            totalSussess = invoiceInfoService.bachSaveDetails(newList);
        } catch (Exception e) {
            e.printStackTrace();
            return success("模板错误");
        }


        int total = dtoList.size();
        int totalFail = total - newList.size();
        String msg = "解析到" + total + "条数据，" + "导入成功" + newList.size() + "条，导入失败" + totalFail + "条！";
        return success(msg);
    }


    @ApiOperation("导入发票百分之三")
    @PostMapping("/importInfoThreePercent")
    public AjaxResult importInfoThreePercent(MultipartFile file) {
        // 获取到批量导入的数据集合
        List<InvoiceInfo> dtoList = null;
        List<InvoiceInfo> newList = new ArrayList<>();
        try {
            dtoList = invoiceInfoService.importInfo(file, "3%发票信息", 3);

            for (InvoiceInfo po : dtoList) {
                newList.add(po);
            }

        } catch (Exception e) {
            e.printStackTrace();
            return success("模板错误");
        }
        int totalSussess = invoiceInfoService.bachSave(newList);
        int total = dtoList.size();
        int totalFail = total - newList.size();
        String msg = "解析到" + total + "条数据，" + "导入成功" + newList.size() + "条，导入失败" + totalFail + "条！";
        return success(msg);
    }


    @ApiOperation("导入发票百分之一")
    @PostMapping("/importInfoOnePercent")
    public AjaxResult importInfoOnePercent(MultipartFile file) {
        // 获取到批量导入的数据集合
        List<InvoiceInfo> dtoList = null;
        List<InvoiceInfo> newList = new ArrayList<>();
        try {
            dtoList = invoiceInfoService.importInfo(file, "1%发票信息", 3);
            for (InvoiceInfo po : dtoList) {
                newList.add(po);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return success("模板错误");
        }
        int totalSussess = invoiceInfoService.bachSave(newList);
        int total = dtoList.size();
        int totalFail = total - newList.size();
        String msg = "解析到" + total + "条数据，" + "导入成功" + newList.size() + "条，导入失败" + totalFail + "条！";
        return success(msg);
    }


    @ApiOperation("完税关联销售收款")
    @PostMapping("/importInfoSalesReceipts")
    public AjaxResult importInfoSalesReceipts(MultipartFile file) {
        // 获取到批量导入的数据集合
        List<InvoiceInfoPaymentRef> dtoList = null;
        List<InvoiceInfoPaymentRef> newList = new ArrayList<>();
        String msg = "";
        try {
            dtoList = invoiceInfoService.importInfoPurchasePayment(file, "完税关联销售收款", 3);
            for (InvoiceInfoPaymentRef po : dtoList) {
                po.setPaymentType("完税关联销售收款");
                newList.add(po);
            }
            int totalSussess = invoiceInfoService.batchSavePaymentRef(newList);
            int total = dtoList.size();
            int totalFail = total - newList.size();
            msg = "解析到" + total + "条数据，" + "导入成功" + newList.size() + "条，导入失败" + totalFail + "条！";
            return success(msg);
        } catch (Exception e) {
            e.printStackTrace();
            return success("模板错误");
        }
    }

    @ApiOperation("完税关联采购付款")
    @PostMapping("/importInfoPurchasePayment")
    public AjaxResult importInfoPurchasePayment(MultipartFile file) {
        // 获取到批量导入的数据集合
        List<InvoiceInfoPaymentRef> dtoList = null;
        List<InvoiceInfoPaymentRef> newList = new ArrayList<>();
        String msg = "";
        try {
            dtoList = invoiceInfoService.importInfoPurchasePayment(file, "完税关联采购付款", 3);
            for (InvoiceInfoPaymentRef po : dtoList) {
                po.setPaymentType("完税关联采购付款");
                newList.add(po);
            }


            int totalSussess = invoiceInfoService.batchSavePaymentRef(newList);
            int total = dtoList.size();
            int totalFail = total - newList.size();
            msg = "解析到" + total + "条数据，" + "导入成功" + newList.size() + "条，导入失败" + totalFail + "条！";
        } catch (Exception e) {
            e.printStackTrace();
            return success("模板错误");
        }
        return success(msg);
    }

    @ApiOperation("完税关联销售出库")
    @PostMapping("/importInfoOutWarehouse")
    public AjaxResult importInfoOutWarehouse(MultipartFile file) {
        // 获取到批量导入的数据集合
        List<InvoiceWarehouseRef> dtoList = null;
        List<InvoiceWarehouseRef> newList = new ArrayList<>();
        int totalSussess = 0;
        try {
            dtoList = invoiceInfoService.importInfoWarehouse(file, "完税关联销售出库", 3);
            for (InvoiceWarehouseRef po : dtoList) {
                po.setCategory("完税关联销售出库");
                if (StringUtils.isEmpty(po.getWarehouseNum())) {
                    po.setWarehouseNum(po.getOutNum());
                    po.setWarehouseAmount(po.getOutSettlementAmount());
                    newList.add(po);
                }
            }

            totalSussess = invoiceInfoService.batchSaveWarehouse(newList);

        } catch (Exception e) {
            e.printStackTrace();
            return success("模板错误");
        }


        int total = dtoList.size();
        int totalFail = total - newList.size();
        String msg = "解析到" + total + "条数据，" + "导入成功" + newList.size() + "条，导入失败" + totalFail + "条！";
        return success(msg);
    }


    @ApiOperation("完税关联采购入库")
    @PostMapping("/importInfoInWarehouse")
    public AjaxResult importInfoInWarehouse(MultipartFile file) {
        // 获取到批量导入的数据集合
        List<InvoiceWarehouseRef> dtoList = null;
        List<InvoiceWarehouseRef> newList = new ArrayList<>();
        int totalSussess = 0;
        try {
            dtoList = invoiceInfoService.importInfoWarehouse(file, "完税关联采购入库", 3);

            for (InvoiceWarehouseRef po : dtoList) {
                po.setCategory("完税关联采购入库");
                if (StringUtils.isEmpty(po.getWarehouseNum())) {
                    po.setWarehouseNum(po.getInNum());
                    po.setWarehouseAmount(po.getInSettlementAmount());
                    newList.add(po);
                }
            }

            totalSussess = invoiceInfoService.batchSaveWarehouse(newList);
            String msg = "解析到" + dtoList.size() + "条数据，" + "导入成功" + totalSussess+ "条，导入失败" +   Math.abs(  dtoList.size()  - totalSussess) + "条！";
            return success(msg);
        }catch (Exception e) {
            e.printStackTrace();
            if(e.getMessage().contains("Incorrect date")){
                String   message =  e.getMessage();
                String truncatedMessage = message.substring(  message.length() - 140  , message.length() );

                return success("日期填写错误" + truncatedMessage);
            }
            return success("模板数据错误");
        }

    }


    @ApiOperation("完税关联合同lv_invoice_info_contract_info_ref")
    @PostMapping("/importInfoContract")
    public AjaxResult importInfoContract(MultipartFile file) {
        // 获取到批量导入的数据集合
        List<InvoiceContractRef> dtoList = null;
        List<InvoiceContractRef> newList = new ArrayList<>();
        String msg = "";
        try {
            dtoList = invoiceInfoService.importInfoContractRef(file, "完税关联合同", 3);

            for (InvoiceContractRef po : dtoList) {

                newList.add(po);
            }

            int totalSussess = invoiceInfoService.bachSaveContractRef(newList);
            int total = dtoList.size();
            int totalFail = total - newList.size();
            msg = "解析到" + total + "条数据，" + "导入成功" + newList.size() + "条，导入失败" + totalFail + "条！";
        } catch (Exception e) {
            e.printStackTrace();
            return success("模板错误");
        }

        return success(msg);
    }


    @ApiOperation("修改物流状态")
    @PostMapping("/updateLogisticsStatusByInvoiceNum")
    public AjaxResult updateLogisticsStatusByInvoiceNum(@RequestBody InvoiceInfo invoiceInfo) {
        int totalSussess = invoiceInfoService.updateLogisticsStatusByInvoiceNum(invoiceInfo);
        return toAjax(totalSussess);
    }


}
